#pragma once

#include "resource.h"
#include "ImageKeeper.h"

class AnalyticBMPApproximation
{
	ImageKeeper mImageKeeper;

	HINSTANCE mInstance;
	HWND mFrameWindow;
	HWND mClientWindow;
	HWND mStatusBarWindow;

	int mPreviousClientWidth, mPreviousClientHeight;
	POINT mScrollPosition;
	double mScale;
	SIZE mOriginalPixelSize;
	SIZE mScaledSize;
	bool mInterpolateOriginalPixels;
	bool mIsMouseReflectedInMagnifier;
	bool mWasMagnifierShown;

	LPARAM mLParamAtLMouseDown;
	DWORD mTimeAtLMouseDown;
	int mPreviousPixelX, mPreviousPixelY;
	int mPreviousScreenX, mPreviousScreenY;

	DWORD mTimeOfLastWheelEvent;
	int mNumberOfRapidWheelEvents;

	int mIndexOfScaleMenu;

public:
	AnalyticBMPApproximation();

	bool InitInstance(HINSTANCE, int cmdShow);
	bool OpenFile(LPCTSTR path);
	int Run();

	static const int kUseWindowCenter = -1;
private:
	bool LocateFile(LPWSTR ioPathBuffer, DWORD bufferLength);
	bool ProcessCommand(int commandId);
	bool UpdateClientSize(int rawClientWidth, int rawClientHeight);

	void SetScrollBars(double coef, int offsetY = kUseWindowCenter, int offsetX = kUseWindowCenter);
	int UpdateScrollbarPosition(int nBar, int command, int thumbPosition);
	void ShowMagnifier(bool);
	void ReflectMousePointer(LPARAM lParam);
	void ShowCoordinatesInStatusBar();
	void SetScaleAndRefresh(double newScale);

	// the parameter lParam contains mouse coordinates
	void RunContextMenu(int submenuPosition, HWND hWnd, LPARAM lParam);

	typedef LRESULT(AnalyticBMPApproximation::*LocalProcedure)(HWND, UINT, WPARAM, LPARAM);
	LRESULT WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	LRESULT WindowProcedureClient(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	LRESULT WindowProcedureMagnifier(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

	static LRESULT CALLBACK WndProcFrame(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK WndProcClient(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK WndProcMagnifier(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	static LRESULT WndProcCommon(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LocalProcedure);
};